using System;
using System.Collections.Generic;
using System.Text;
using NUnit.Framework;
using System.Data;
using System.Data.OleDb;

namespace Dbam.DbFramework.Tests
{
    [TestFixture]
	public class OleDbFactoryTests
	{
		[SetUp]
		public void SetupTest()
		{
			string cmdText = "Delete From [Accounts] Where 1 = 1";
			OleDbFactory dbFactory = new OleDbFactory(TestSettings.Default.OleDbConnStr);
			dbFactory.CreateCommand(cmdText).ExecuteNonQuery();
			dbFactory.Dispose();
		}

        [Test]
		public void InsertUpdateDeleteEntityTest()
		{
			AccountEntity account = new AccountEntity();
			account.AccountId = Guid.NewGuid();
			account.Name = "Test Account";
			account.LastLogon = null;
			account.MemberSince = DateTime.Now;

			OleDbFactory dbFactory = new OleDbFactory(TestSettings.Default.OleDbConnStr);
			Assert.IsTrue(dbFactory.InsertEntity(account));
			Assert.IsTrue(dbFactory.DeleteEntity(account));

			dbFactory.InsertEntity(account);
			account.Name = "Test Account (Updated)";
			dbFactory.UpdateEntity(account);
			Assert.IsTrue(dbFactory.EntityExists(account));
			account.AccountId = new Guid();
			Assert.IsFalse(dbFactory.EntityExists(account));
		}

        [Test]
        public void ConnectDisconnectTest()
        {
			OleDbFactory dbFactory = new OleDbFactory(TestSettings.Default.OleDbConnStr);
            dbFactory.Disconnect();
        }

		[Test]
		public void ConnectDisconnectTwiceTest()
		{
			OleDbFactory dbFactory = new OleDbFactory(TestSettings.Default.OleDbConnStr);
			dbFactory.Disconnect();
			dbFactory.Disconnect();
		}

		[Test]
		[ExpectedException(typeof(InvalidOperationException))]
		public void ConnectTwiceTest()
		{
			OleDbFactory dbFactory = new OleDbFactory(TestSettings.Default.OleDbConnStr);
			dbFactory.Connect(TestSettings.Default.TestDbConnectionString);
		}

		[Test]
		public void CreateCommandAfterDisconnectTest()
		{
			OleDbFactory dbFactory = new OleDbFactory(TestSettings.Default.OleDbConnStr);
			dbFactory.Disconnect();
			IDbCommand command = dbFactory.CreateCommand("select * from [Accounts]");
		}

		[Test]
		public void CreateAndSelectTest()
		{
			OleDbFactory dbFactory = new OleDbFactory(TestSettings.Default.OleDbConnStr);

			for(int index = 1; index <= 5; index++)
			{
				AccountEntity account = new AccountEntity();
				account.Name = string.Format("User {0}", index);
				account.AccountId = new Guid(string.Format("00000000-0000-0000-0000-00000000000{0}", index));
				account.LastLogon = DateTime.Now;
				account.MemberSince = DateTime.Parse(@"1/1/2000");
				dbFactory.InsertEntity(account);


				AccountEntity fetchedEntity = new AccountEntity();
				fetchedEntity.AccountId = new Guid(string.Format("00000000-0000-0000-0000-00000000000{0}", index));
				dbFactory.SelectEntity(fetchedEntity);
				Assert.AreEqual(account.AccountId, fetchedEntity.AccountId);
				Assert.AreEqual(account.Name, fetchedEntity.Name);
				Assert.AreEqual(account.LastLogon.Value.ToShortDateString(), fetchedEntity.LastLogon.Value.ToShortDateString());
				Assert.AreEqual(account.MemberSince, fetchedEntity.MemberSince);
			}
		}

		[Test]
		public void DeleteEntityOnConnectionClosedTest()
		{
			OleDbFactory dbFactory = new OleDbFactory(TestSettings.Default.OleDbConnStr);
			AccountEntity account = new AccountEntity();
			account.Name = string.Format("User 1");
			account.AccountId = Guid.NewGuid();
			account.LastLogon = DateTime.Now;
			account.MemberSince = DateTime.Parse(@"1/1/2000");
			dbFactory.InsertEntity(account);
			dbFactory.Disconnect();
			dbFactory.DeleteEntity(account);
		}

		[Test]
		public void SelectNonExistentEntityTest()
		{
			OleDbFactory dbFactory = new OleDbFactory(TestSettings.Default.OleDbConnStr);
			AccountEntity account = new AccountEntity();
			Assert.IsFalse(dbFactory.EntityExists(account));
			Assert.IsFalse(dbFactory.SelectEntity(account));
		}

		[Test]
		[ExpectedException(typeof(ArgumentException))]
		public void InvalidSelectCommandTypeTest()
		{
			OleDbFactory dbFactory = new OleDbFactory(TestSettings.Default.OleDbConnStr);
			IDataAdapter adp = dbFactory.CreateAdapter(new OleDbCommand(), null, null, null);
		}

		[Test]
		[ExpectedException(typeof(ArgumentException))]
		public void InvalidInsertCommandTypeTest()
		{
			OleDbFactory dbFactory = new OleDbFactory(TestSettings.Default.OleDbConnStr);
			IDataAdapter adp = dbFactory.CreateAdapter(null, new OleDbCommand(), null, null);
		}

		[Test]
		[ExpectedException(typeof(ArgumentException))]
		public void InvalidUpdateCommandTypeTest()
		{
			OleDbFactory dbFactory = new OleDbFactory(TestSettings.Default.OleDbConnStr);
			IDataAdapter adp = dbFactory.CreateAdapter(null, null, new OleDbCommand(), null);
		}

		[Test]
		[ExpectedException(typeof(ArgumentException))]
		public void InvalidDeleteCommandTypeTest()
		{
			OleDbFactory dbFactory = new OleDbFactory(TestSettings.Default.OleDbConnStr);
			IDataAdapter adp = dbFactory.CreateAdapter(null, null, null, new OleDbCommand());
		}

		[Test]
		public void TryDeleteEntityOnClosedConnectionTest()
		{
			OleDbFactory dbFactory = new OleDbFactory(TestSettings.Default.OleDbConnStr);
			dbFactory.Disconnect();
			dbFactory.DeleteEntity(new AccountEntity());
		}

		[Test]
		[ExpectedException(typeof(ArgumentNullException))]
		public void TryDeleteNullEntityTest()
		{
			OleDbFactory dbFactory = new OleDbFactory(TestSettings.Default.OleDbConnStr);
			dbFactory.DeleteEntity(null);
		}

		[Test]
		[ExpectedException(typeof(ArgumentException))]
		public void TryConnectWithNullAndEmptyConnectionString()
		{
			OleDbFactory dbFactory = new OleDbFactory(null);
			dbFactory = new OleDbFactory(string.Empty);
		}

		[Test]
		[ExpectedException(typeof(ApplicationException))]
		public void TryConnectWithInvalidConnectionStringTest()
		{
			OleDbFactory dbFactory = new OleDbFactory("data source=dbam-mac; database=dbnoexist");
		}

		[Test]
		public void AddParamsTest()
		{
			OleDbFactory dbFactory = new OleDbFactory(TestSettings.Default.OleDbConnStr);
			IDbCommand cmd = dbFactory.CreateCommand("select * from something");
			dbFactory.AddInputParam(cmd, "param1", DbType.Int32, 1);
			dbFactory.AddOutputParam(cmd, "param2", DbType.String, "test");
			dbFactory.AddInputOutputParam(cmd, "param3", DbType.Guid, Guid.NewGuid());
			dbFactory.AddReturnValueParam(cmd, "param4", DbType.Int32, null);

			Assert.IsNotNull(cmd.Parameters["param1"]);
			Assert.IsNotNull(cmd.Parameters["param2"]);
			Assert.IsNotNull(cmd.Parameters["param3"]);
			Assert.IsNotNull(cmd.Parameters["param4"]);
		}
	}
}